package com.utilities.IO.fileWriters;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;

import com.utilities.parsers.gbkFileParser.ParseEvents;
import com.utilities.parsers.gbkFileParser.ParseGBKFileParser;
import com.utilities.parsers.gbkFileParser.ParseListener;

public class PrepareRefGeneFile  extends ParseListener{
	
	private ParseGBKFileParser fileParser = null;
	private HashMap<String,ArrayList<String>> geneMap = 
		new HashMap<String, ArrayList<String>>();
	private HashMap<String,ArrayList<String>> cdsMap = 
		new HashMap<String, ArrayList<String>>();
	private String lastGene = null;
	public static void main(String[] args) throws Exception
	{
		PrepareRefGeneFile parser = new PrepareRefGeneFile();
		parser.fileParser = new ParseGBKFileParser();
		parser.fileParser.addListener(parser);
		parser.fileParser.parse(new File("C:/Users/bansalp/Desktop/data/gbkFile.gbk"));
		parser.writeFiles("C:/Users/bansalp/Desktop/data/geneFile1.txt","C:/Users/bansalp/Desktop/data/cdsFile1.txt",
				"C:/Users/bansalp/Desktop/data/geneMinuscdsFile.txt","C:/Users/bansalp/Desktop/data/cdsMinusgeneFile.txt");
		parser.writeRefGenefile("C:/Users/bansalp/Desktop/data/refGene.txt");
	}
	private void writeRefGenefile(String refGeneFile) throws Exception
	{
		Random rand = new Random();
		StringBuffer buffer = new StringBuffer();
		PrintWriter pw = new PrintWriter(refGeneFile);
		Set<String> keySet = geneMap.keySet();
		for(String key : keySet)
		{
			ArrayList<String> gene_positionInfos = geneMap.get(key);
			ArrayList<String> cds_positionInfos = cdsMap.get(key);
			
			if (gene_positionInfos.size() != cds_positionInfos.size() )
			{
				System.out.println(key + " has unequal hits");
				System.exit(-1);
			}
			for (int i = 0 ; i < gene_positionInfos.size();i++)
			{
				String[] gene_pos = gene_positionInfos.get(i).split("\t");
				String[] cds_pos = cds_positionInfos.get(i).split("\t");
				if (!gene_pos[1].equalsIgnoreCase(cds_pos[1]))
				{
					System.out.println(key + " is in differnt orientations");
					System.exit(-1);
				}
				else if (!gene_pos[0].equalsIgnoreCase(cds_pos[0]))
				{
					System.out.println(key + " has different annotation in cds and gene file");
					System.out.println(cds_pos[0] + " \n" + gene_pos[0]);
					System.exit(-1);
				}
				int id = rand.nextInt(4500);
				buffer.append(String.format("%s\t%s\tchr01\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
						id,key,gene_pos[1],
						gene_pos[0].split("\\.\\.")[0],gene_pos[0].split("\\.\\.")[1],cds_pos[0].split("\\.\\.")[0],
						cds_pos[0].split("\\.\\.")[1],0,"","",id,"","none","none",-1));
				pw.println(buffer.toString());
				buffer = new StringBuffer();
			}
		}
		pw.flush();
		pw.close();
	}
	private void writeFiles(String geneFile, String cdsFile, String geneMinusCdsFile, String cdsMinusGeneFile) throws FileNotFoundException {
		PrintWriter pw = new PrintWriter(geneFile);
		Set<String> keySet = geneMap.keySet();
		for(String key : keySet)
		{
			ArrayList<String> positionInfos = geneMap.get(key);
			for(String pos : positionInfos)
			{
				pw.println(String.format("%s\t%s", key,pos));
			}
		}
		pw.flush();
		pw.close();
		
		pw = new PrintWriter(cdsFile);
		Set<String> keySet2 = cdsMap.keySet();
		for(String key : keySet2)
		{
			ArrayList<String> positionInfos = cdsMap.get(key);
			for(String pos : positionInfos)
			{
				pw.println(String.format("%s\t%s", key,pos));
			}
		}
		pw.flush();
		pw.close();
		
//		keySet.removeAll(keySet2);
//		pw = new PrintWriter(geneMinusCdsFile);
//		for(String key : keySet)
//		{
//			pw.println(key);
//		}
//		pw.flush();
//		pw.close();
		
//		keySet2.removeAll(geneMap.keySet());
//		
//		pw = new PrintWriter(cdsMinusGeneFile);
//		for(String key : keySet2)
//		{
//			pw.println(key);
//		}
//		pw.flush();
//		pw.close();
	}
	@Override
	public void handleEvent(ParseEvents event) {
		try
		{
			switch((ParseEvents.EventTypes)event.getEventType())
			{
				case docStarted : break;
				case docEnded: break;
				case sequenceStart: 
				{
					fileParser.setStopReading(true);
					break;
				}
				case rRNA:
				case tRNA:
				case cds: 
				{
					String cdsName = fileParser.getFeatureName();
					String positionInfo = fileParser.getPositionalInfo();
					// This is to check that we are not reading a gene info with no position info
					assert(positionInfo != null);
					String orientation = "+";
					if (positionInfo.contains("complement"))
					{
						orientation = "-";
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.lastIndexOf(")"));
					}
					if (positionInfo.contains("join"))
					{
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.indexOf(")")); 
						String[] subParts = positionInfo.split(",");
						String start = subParts[0].split("\\.\\.")[0];
						String end = subParts[subParts.length - 1].split("\\.\\.")[1];
						positionInfo = start+".."+end;
					}
					positionInfo = positionInfo + "\t" + orientation;
					ArrayList<String> list = null;
					// if we have already read this gene before
					if (cdsMap.containsKey(cdsName))
					{
						// fetch the positions list corresponding to this geneName
						list = cdsMap.get(cdsName);
					}
					else
					{
						list = new ArrayList<String>();
					}
					list.add(positionInfo);
					cdsMap.put(cdsName, list);
					break;
				}
				case tmRNA:
				case ncRNA:
				{
					String positionInfo = fileParser.getPositionalInfo();
					// This is to check that we are not reading a gene info with no position info
					assert(positionInfo != null);
					String orientation = "+";
					if (positionInfo.contains("complement"))
					{
						orientation = "-";
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.lastIndexOf(")"));
					}
					if (positionInfo.contains("join"))
					{
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.indexOf(")")); 
						String[] subParts = positionInfo.split(",");
						String start = subParts[0].split("\\.\\.")[0];
						String end = subParts[subParts.length - 1].split("\\.\\.")[1];
						positionInfo = start+".."+end;
					}
					positionInfo = positionInfo + "\t" + orientation;
					ArrayList<String> list = null;
					// if we have already read this gene before
					if (cdsMap.containsKey(lastGene))
					{
						// fetch the positions list corresponding to this geneName
						list = cdsMap.get(lastGene);
					}
					else
					{
						list = new ArrayList<String>();
					}
					list.add(positionInfo);
					cdsMap.put(lastGene, list);
					break;
				}
					
				case gene:
				{
					String geneName = fileParser.getFeatureName();
					String positionInfo = fileParser.getPositionalInfo();
					// This is to check that we are not reading a gene info with no position info
					assert(positionInfo != null);
					String orientation = "+";
					if (positionInfo.contains("complement"))
					{
						orientation = "-";
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.lastIndexOf(")"));
					}
					if (positionInfo.contains("join"))
					{
						positionInfo = positionInfo.substring(positionInfo.indexOf("(") + 1,positionInfo.indexOf(")")); 
						String[] subParts = positionInfo.split(",");
						String start = subParts[0].split("\\.\\.")[0];
						String end = subParts[subParts.length - 1].split("\\.\\.")[1];
						positionInfo = start+".."+end;
					}
					positionInfo = positionInfo + "\t" + orientation;
					ArrayList<String> list = null;
					// if we have already read this gene before
					if (geneMap.containsKey(geneName))
					{
						// fetch the positions list corresponding to this geneName
						list = geneMap.get(geneName);
					}
					else
					{
						list = new ArrayList<String>();
					}
					list.add(positionInfo);
					geneMap.put(geneName, list);
					lastGene = geneName;
					break;
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.err.println();
			System.exit(-1);
		}
	}
}
